package ms.unicorn.util;

import java.util.ArrayList;

import ms.unicorn.Element;
import ms.unicorn.diagram.edit.parts.DiagramEditPart;
import ms.unicorn.diagram.part.UnicornDiagramEditorPlugin;
import ms.unicorn.diagram.part.UnicornVisualIDRegistry;
import ms.unicorn.dsl.IFigureEx;

import org.eclipse.draw2d.IFigure;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
import org.eclipse.gmf.runtime.diagram.ui.preferences.IPreferenceConstants;
import org.eclipse.gmf.runtime.draw2d.ui.figures.FigureUtilities;
import org.eclipse.gmf.runtime.notation.Connector;
import org.eclipse.gmf.runtime.notation.DecorationNode;
import org.eclipse.gmf.runtime.notation.FontStyle;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.NotationFactory;
import org.eclipse.gmf.runtime.notation.NotationPackage;
import org.eclipse.gmf.runtime.notation.RelativeBendpoints;
import org.eclipse.gmf.runtime.notation.Routing;
import org.eclipse.gmf.runtime.notation.Shape;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.RGB;

public class ViewUtil extends
		org.eclipse.gmf.runtime.diagram.core.util.ViewUtil {

	public static final int VIEW_PRIMARY_CHILD = 1;
	
	public static void stampShortcut(View containerView, Node target) {
		if (!DiagramEditPart.MODEL_ID.equals(UnicornVisualIDRegistry
				.getModelID(containerView))) {
			EAnnotation shortcutAnnotation = EcoreFactory.eINSTANCE
					.createEAnnotation();
			shortcutAnnotation.setSource("Shortcut"); //$NON-NLS-1$
			shortcutAnnotation.getDetails().put(
					"modelID", DiagramEditPart.MODEL_ID); //$NON-NLS-1$
			target.getEAnnotations().add(shortcutAnnotation);
		}
	}
	
	public static View getChildView(View owner, int flag) {
		int vflag = getViewFlag(owner);
			if ((vflag & flag) > 0) return owner;
		for (Object child: owner.getChildren())
			if (child instanceof View) {
				View fig = getChildView((View) child, flag);
				if (fig != null)
					return fig;
			}
		return null;
	}

	public static Node createLabel(String name, View owner, String type, String parser, int flag) {
		DecorationNode rv = NotationFactory.eINSTANCE.createDecorationNode();
		setViewName(rv, name);
		setViewParser(rv, parser);
		setViewFlag(rv, flag);
		rv.setType(type);
		rv.setLayoutConstraint(NotationFactory.eINSTANCE.createLocation());
		ViewUtil.insertChildView(owner, rv, ViewUtil.APPEND, true);
		return rv;
	}
	
	public static Shape createNode(String name, Element entity, PreferencesHint preferencesHint, String type) {
		Shape node = NotationFactory.eINSTANCE.createShape();
		
		setViewName(node, name);
		
		node.setLayoutConstraint(NotationFactory.eINSTANCE.createBounds());				
		node.setType(type);
		
		node.setElement(entity);
		//ViewUtil.stampShortcut(containerView, node);
		
		// initializeFromPreferences 
		if (preferencesHint == null)
			preferencesHint = UnicornDiagramEditorPlugin.DIAGRAM_PREFERENCES_HINT;
		
		final IPreferenceStore prefStore = (IPreferenceStore) preferencesHint.getPreferenceStore();
		
		
		RGB lineRGB = PreferenceConverter.getColor(prefStore, IPreferenceConstants.PREF_LINE_COLOR);
		ViewUtil.setStructuralFeatureValue(node,
				NotationPackage.eINSTANCE.getLineStyle_LineColor(),
				FigureUtilities.RGBToInteger(lineRGB));
		FontStyle nodeFontStyle = (FontStyle) node
				.getStyle(NotationPackage.Literals.FONT_STYLE);
		if (nodeFontStyle != null) {
			FontData fontData = PreferenceConverter.getFontData(prefStore, IPreferenceConstants.PREF_DEFAULT_FONT);
			nodeFontStyle.setFontName(fontData.getName());
			nodeFontStyle.setFontHeight(fontData.getHeight());
			nodeFontStyle.setBold((fontData.getStyle() & SWT.BOLD) != 0);
			nodeFontStyle.setItalic((fontData.getStyle() & SWT.ITALIC) != 0);
			RGB fontRGB = PreferenceConverter.getColor(prefStore, IPreferenceConstants.PREF_FONT_COLOR);
			nodeFontStyle.setFontColor(FigureUtilities.RGBToInteger(fontRGB).intValue());
		}
		RGB fillRGB = PreferenceConverter.getColor(
				prefStore, IPreferenceConstants.PREF_FILL_COLOR);
		ViewUtil.setStructuralFeatureValue(node,
				NotationPackage.eINSTANCE.getFillStyle_FillColor(),
				FigureUtilities.RGBToInteger(fillRGB));
		return node;
	}
	
	@SuppressWarnings("unchecked")
	public static Connector createConnector(String name, Element relation, PreferencesHint preferencesHint, String type) {
		Connector edge = NotationFactory.eINSTANCE.createConnector();
		setViewName(edge, name);
		edge.setType(type);
		
		edge.getStyles().add(NotationFactory.eINSTANCE.createFontStyle());		
		
		RelativeBendpoints bendpoints = NotationFactory.eINSTANCE
				.createRelativeBendpoints();
		ArrayList<RelativeBendpoint> points = new ArrayList<RelativeBendpoint>(2);
		points.add(new RelativeBendpoint());
		points.add(new RelativeBendpoint());
		bendpoints.setPoints(points);
		edge.setBendpoints(bendpoints);
		
		edge.setElement(relation);

		if (preferencesHint == null)
			preferencesHint = UnicornDiagramEditorPlugin.DIAGRAM_PREFERENCES_HINT;
		
		// initializePreferences
		final IPreferenceStore prefStore = (IPreferenceStore) preferencesHint
				.getPreferenceStore();
	
		org.eclipse.swt.graphics.RGB lineRGB = PreferenceConverter.getColor(
				prefStore, IPreferenceConstants.PREF_LINE_COLOR);
		ViewUtil.setStructuralFeatureValue(edge,
				NotationPackage.eINSTANCE.getLineStyle_LineColor(),
				FigureUtilities.RGBToInteger(lineRGB));
		FontStyle edgeFontStyle = (FontStyle) edge
				.getStyle(NotationPackage.Literals.FONT_STYLE);
		if (edgeFontStyle != null) {
			FontData fontData = PreferenceConverter.getFontData(prefStore,
					IPreferenceConstants.PREF_DEFAULT_FONT);
			edgeFontStyle.setFontName(fontData.getName());
			edgeFontStyle.setFontHeight(fontData.getHeight());
			edgeFontStyle.setBold((fontData.getStyle() & SWT.BOLD) != 0);
			edgeFontStyle.setItalic((fontData.getStyle() & SWT.ITALIC) != 0);
			org.eclipse.swt.graphics.RGB fontRGB = PreferenceConverter
					.getColor(prefStore, IPreferenceConstants.PREF_FONT_COLOR);
			edgeFontStyle.setFontColor(FigureUtilities.RGBToInteger(fontRGB)
					.intValue());
		}
		Routing routing = Routing.get(prefStore
				.getInt(IPreferenceConstants.PREF_LINE_STYLE));
		
		if (routing != null) {
			ViewUtil.setStructuralFeatureValue(edge,
					NotationPackage.eINSTANCE.getRoutingStyle_Routing(),
					routing);
		}
		return edge;
	}
	
	
	public static String getViewName(View view) {
		return getViewDefField(view, "subview.name");
	}
	
	public static void setViewName(View view, String name) {
		setViewDefField(view, "subview.name", name);
	}
	
	public static String getViewParser(View view) {
		return getViewDefField(view, "parser");
	}
	
	public static void setViewParser(View view, String parser) {
		setViewDefField(view, "parser", parser);
	}
	
	public static int getViewFlag(View view) {
		String s = getViewDefField(view, "flag");
		return s == null ? 0 : Integer.decode(s);
	}
	
	public static void setViewFlag(View view, int flag) {
		setViewDefField(view, "flag", Integer.toString(flag));
	}
	
	public static String getQualifiedViewName(View view) {
		String name = getViewName(view);
		if (name != null && view.eContainer() instanceof View) {
			String pName = getQualifiedViewName((View)view.eContainer());
			if (pName != null)
				name = pName + ':' + name;
		}
		return name;
	}
	
	public static String getViewDefField(View view, String field) {
		EAnnotation viewNameAnno = view.getEAnnotation("definition");
		if (viewNameAnno != null) 
			return viewNameAnno.getDetails().get(field);
		return null;
	}
	
	public static void setViewDefField(View view, String field, String value) {
		EAnnotation viewNameAnno = view.getEAnnotation("definition");
		if (viewNameAnno == null) {
			viewNameAnno = EcoreFactory.eINSTANCE.createEAnnotation();
			viewNameAnno.setSource("definition");
			view.getEAnnotations().add(viewNameAnno);
		}
		viewNameAnno.getDetails().put(field, value);
	}
}
